package edu.spsu.mail;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.Properties;

import javax.mail.Folder;
import javax.mail.Message;
import javax.mail.Session;
import javax.mail.Store;

import android.app.ProgressDialog;
import android.content.Context;
import android.content.SharedPreferences;
import android.text.SpannableString;
import android.text.util.Linkify;
import android.widget.ArrayAdapter;

import com.sun.mail.imap.IMAPInputStream;
import com.sun.mail.util.MailSSLSocketFactory;

import edu.spsu.R;
import edu.spsu.utils.UIUtils;
import edu.spsu.utils.Util;

public final class EmailState
{
	private static Message[] message;
	private static String[] preface = new String[]{ "No Messages available." };
	private static Properties props;
	private static Session session;
	private static Folder folder;
	private static Store store;
	private static boolean connected = false;

	private static String TAG;
	private static EmailListingActivity context;
	private static ProgressDialog progress;


	public static void setUpEmailState(Context con, String tag)
	{
		TAG = tag;
		context = (EmailListingActivity)con;

		props = new Properties();
		props.setProperty("mail.store.protocol", "imaps");
		props.setProperty("mail.imaps.socketFactory.class",
				"javax.net.ssl.SSLSocketFactory");

		props.setProperty("mail.imaps.socketFactory.fallback",
				"false");
		props.setProperty("mail.imaps.ssl.enable", "true");

		props.setProperty("mail.imaps.ssl.trust",
				"zimbra.spsu.edu");
		props.setProperty("mail.imaps.socketFactory.host",
				"zimbra.spsu.edu");

		props.setProperty("mail.imaps.socketFactory.port",
				Integer.toString(993));
		props.setProperty("mail.imaps.timeout",
				Integer.toString(45000));

		props.setProperty("mail.imaps.connectionpooltimeout",
				Integer.toString(45000));
		props.setProperty("mail.imaps.connectiontimeout",
				Integer.toString(45000));
	}

	public static void makeConnection() {

		if(!isSetUp() || connected()) return;
		
		new Thread(new Runnable() {

			@Override
			public void run() {

				context.runOnUiThread(new Thread() {
					public void run() {
						ArrayAdapter<String> adapter = new ArrayAdapter<String>(
								context,
								android.R.layout.simple_list_item_1,
								preface);
						context.setListAdapter(adapter);

						progress = UIUtils.showProgressDialog(context,"Zimbra Email Client", context.getString(R.string.messages_0) +" "+Util.INBOX_MESSAGES+" "+context.getString(R.string.messages_1));
					}
				});

				SharedPreferences sp = Util.getPref(context);
				String user = sp.getString("user", null);
				String pass = sp.getString("pass", null);
				//Util.INBOX_MESSAGES = sp.getInt("inbox", 40);

				if (user != null && pass != null)
				{
					try
					{
						MailSSLSocketFactory sf = new MailSSLSocketFactory();
						sf.setTrustAllHosts(true);

						props.put("mail.imaps.ssl.socketFactory", sf);
						session = Session.getInstance(props);

						store = session.getStore();
						store.connect("zimbra.spsu.edu", 993, user, pass);

						folder = store.getFolder("INBOX");
						folder.open(Folder.READ_ONLY);
						
						connected = true;
						Util.report(context, TAG, "Connected to Zimbra", false);
						
						retrieveInboxMessages(Util.INBOX_MESSAGES);
						Util.report(context, TAG, "Inbox messages have been populated.", false);
					}
					catch (Exception ex) {
						Util.report(context, TAG, "Exception Thrown: "+ex, true);
					}
				}
				else{
					Util.report(context, TAG, "Not able to connect to Zimbra. Check your credentials!", false);
				}
			}
		}).start();
	}


	public static String[] getPrefaceArray() {
		//		if(!isReady()) return null;

		return preface;
	}

	public static String getPreface(int pos) {
		//		if(!isReady()) return null;

		if(pos < 0 || pos >=preface.length) 
			return "Not in the list";

		return preface[pos];
	}
	
	public static Message[] getMessageArray(){
		//		if(!isReady()) return null;

		return message;
	}


	public static boolean isSetUp() { return props != null; }

	public static boolean connected() { return connected; }

	public static boolean messagesRecieved() { return message != null; }


	public static String getMessageHeader(int pos) {

		if(pos < 0 || pos >= message.length)
			return null;

		String data = null, subject = null;
		Message mes = message[pos];

		try {

			int month = mes.getSentDate().getMonth();
			String[] months = {"Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"};

			data = ""+mes.getSentDate().getDay() +" "+months[month] +" From: "+mes.getFrom()[0];
			subject = "\n" + mes.getSubject();

		} catch (Exception e) {
			Util.report(context, TAG, "Exception Thrown: "+e, true);
		}

		int len = subject.length();
		
		return data+" "+subject.substring(0,len < 40 ? len : 40);
	}

	public static SpannableString getMessage(int pos) {

		if(pos < 0 || pos >= message.length)
			return null;

		SpannableString s = null;
		Message mes = message[pos];

		try{
			Object o = mes.getContent();
			BufferedReader br = new BufferedReader(new InputStreamReader((IMAPInputStream)o));
			String oneLine = "", msg = "";

			while ((oneLine = br.readLine()) !=  null)
				msg +=(oneLine +"\n");

			// Linkify the message
			s = new SpannableString(msg);
			Linkify.addLinks(s, Linkify.ALL);

		}
		catch (Exception ex) {
			Util.report(context, TAG, "Exception Thrown: "+ex, true);
		}

		return s;
	}

	public static void retrieveInboxMessages(final int message_num) {
		
		new Thread(new Runnable() {

			@Override
			public void run() {
				
				try{

					// Get directory
					message = new Message[message_num];
					preface = new String[message_num];
					
					int size = folder.getMessageCount();

					for (int j = size; j >= size - message_num + 1; j--) {
						int index = size - j;
						message[index] = folder.getMessage(j);
						
						preface[index] = (message[index].getSubject() + 
						"\n\t\tFrom:\t" + message[index].getFrom()[0]);
					}

					context.runOnUiThread(new Thread() {
						public void run() {
							ArrayAdapter<String> adapter = new ArrayAdapter<String>(
									context,
									android.R.layout.simple_list_item_1,
									preface);
							context.setListAdapter(adapter);

							UIUtils.hideProgressDialog(progress);
						}
					});
				}
				catch (Exception ex) {
					connected = false;

					context.runOnUiThread(new Thread() {
						public void run() {

							ArrayAdapter<String> adapter = new ArrayAdapter<String>(
									context,
									android.R.layout.simple_list_item_1,
									preface);
							context.setListAdapter(adapter);
							UIUtils.hideProgressDialog(progress);
						}
					});
					Util.report(context, TAG, "Exception Thrown: "+ex, true);
				}
			}
		}).start();
	}

	public static void disconnect()
	{
//		try
//		{
//			if(folder.isOpen()) folder.close(true);
//			if(store.isConnected()) store.close();
//			connected = false;
//		}
//		catch (Exception ex) {
//			Util.report(context, TAG, "Exception Thrown: "+ex, true);
//		}
	}

	public static void makeConnection(final String user,final String pass) {

		if(!isSetUp() || connected()) return;
		
		new Thread(new Runnable() {

			@Override
			public void run() {

				context.runOnUiThread(new Thread() {
					public void run() {
						ArrayAdapter<String> adapter = new ArrayAdapter<String>(
								context,
								android.R.layout.simple_list_item_1,
								preface);
						context.setListAdapter(adapter);

						progress = UIUtils.showProgressDialog(context,"Zimbra Email Client", context.getString(R.string.messages_0) +" "+Util.INBOX_MESSAGES+" "+context.getString(R.string.messages_1));
					}
				});
				
				if (user != null && pass != null)
				{
					try
					{
						MailSSLSocketFactory sf = new MailSSLSocketFactory();
						sf.setTrustAllHosts(true);

						props.put("mail.imaps.ssl.socketFactory", sf);
						session = Session.getInstance(props);

						store = session.getStore();
						store.connect("zimbra.spsu.edu", 993, user, pass);

						folder = store.getFolder("INBOX");
						folder.open(Folder.READ_ONLY);
						
						connected = true;
						Util.report(context, TAG, "Connected to Zimbra", false);
						
						retrieveInboxMessages(Util.INBOX_MESSAGES);
						Util.report(context, TAG, "Inbox messages have been populated.", false);
					}
					catch (Exception ex) {
						Util.report(context, TAG, "Exception Thrown: "+ex, true);
					}
				}
				else{
					Util.report(context, TAG, "Not able to connect to Zimbra. Check your credentials!", false);
				}
			}
		}).start();
	}

}
